﻿using System.Collections.Generic;
using System.Diagnostics;
using TrueSync;
using UnityEngine;

namespace HEFramework
{
    public static class SkillEffectExecutionComponentSystem
    {
        [EntitySystem]
        public class SkillEffectExecutionComponentAwakeSystem : AwakeSystem<SkillEffectExecutionComponent>
        {
            protected override void Awake(SkillEffectExecutionComponent _self)
            {
            }
        }


        [EntitySystem]
        public class SkillEffectExecutionComponentUpdateSystem : UpdateSystem<SkillEffectExecutionComponent>
        {
            protected override void Update(SkillEffectExecutionComponent _self)
            {
                _self.UpdateAddBuffs();
                _self.UpdateBuffs();
                _self.UpdateRemoveBuffs();
            }
        }


        /// <summary>
        /// 执行效果
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_id"></param>
        /// <param name="_receiver"></param>
        /// <param name="_pos"></param>
        /// <returns></returns>
        public static int Execute(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);

            if (data.IsBuff == 1)
            {
                _self.AddBuff(_id, _receiver, _pos);
            }
            else
            {
                if (_self.ConditionPass(_id, _receiver, _pos) == 0)
                {
                    return 0;
                }

                _self.Do(_id, _receiver, _pos);
            }

            return 1;
        }

        /// <summary>
        /// 移除效果
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_id"></param>
        /// <param name="_receiver"></param>
        /// <param name="_pos"></param>
        /// <returns></returns>
        public static int Remove(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return 0;
            }

            if (data.IsBuff == 1)
            {
                _self.RemoveBuff(_id, _receiver, _pos);
            }

            return 1;
        }

        /// <summary>
        /// 销毁效果
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_id"></param>
        /// <param name="_receiver"></param>
        /// <param name="_pos"></param>
        /// <returns></returns>
        public static int Destroy(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return 0;
            }

            if (data.IsBuff == 1)
            {
                _self.DestroyBuff(_id, _receiver, _pos);
            }

            return 1;
        }

        /// <summary>
        /// 条件判定
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_id"></param>
        /// <param name="_receiver"></param>
        /// <param name="_pos"></param>
        /// <returns></returns>
        private static int ConditionPass(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return 0;
            }

            //是否标记为一定通过
            if (data.ConditionATypes[0] == (int)eSkillEffectConditionType.None)
            {
                return 1;
            }

            //是否需要进行条件判断
            for (int i = 0; i < data.ConditionATypes.Length; i++)
            {
                var judgen = data.JudgenTypes[i];
                //判断是否需要判断
                if (judgen == (int)eSkillEffectJudgenType.None)
                {
                    continue;
                }

                FP valueA = _self.GetConditionValue(data.ConditionATypes[i], data.ConditionAValues[i], _id, _receiver, _pos);
                FP valueB = _self.GetConditionValue(data.ConditionBTypes[i], data.ConditionBValues[i], _id, _receiver, _pos);

                switch (judgen)
                {
                    case (int)eSkillEffectJudgenType.Upward:
                        //大于 -> 小于等于
                        if (valueA <= valueB)
                        {
                            return 0;
                        }

                        break;
                    case (int)eSkillEffectJudgenType.Under:
                        //小于 -> 大于等于
                        if (valueA >= valueB)
                        {
                            return 0;
                        }

                        break;
                    case (int)eSkillEffectJudgenType.Equal:
                        //等于 -> 不等于
                        if (valueA != valueB)
                        {
                            return 0;
                        }

                        break;
                    case (int)eSkillEffectJudgenType.UpwardEqual:
                        //大于等于 -> 小于
                        if (valueA < valueB)
                        {
                            return 0;
                        }

                        break;
                    case (int)eSkillEffectJudgenType.UnderEqual:
                        //小于等于 ->大于
                        if (valueA > valueB)
                        {
                            return 0;
                        }

                        break;
                }
            }


            return 1;
        }

        /// <summary>
        /// 条件值获取
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_id"></param>
        /// <param name="_value"></param>
        /// <param name="_eID"></param>
        /// <param name="_receiver"></param>
        /// <param name="_pos"></param>
        /// <returns></returns>
        private static FP GetConditionValue(this SkillEffectExecutionComponent _self, int _id, int _value, int _eID, Entity _receiver, TSVector _pos)
        {
            //条件未填则直接返回值
            if (_id == (int)eSkillEffectConditionType.None)
            {
                return _value;
            }

            var ac = _receiver.GetChild<AttributeComponent>();
            if (ac == null)
            {
                return 0;
            }

            switch (_id)
            {
                case (int)eSkillEffectConditionType.HP:
                    return ac.GetValue((int)eAttribute.HP, _value);
                case (int)eSkillEffectConditionType.HP_PCT:
                    return ac.GetValue((int)eAttribute.HP_PCT, _value);
                case (int)eSkillEffectConditionType.X_HP:
                    return ac.GetValue((int)eAttribute.X_HP, _value);
                case (int)eSkillEffectConditionType.X_HP_PCT:
                    return ac.GetValue((int)eAttribute.X_HP_PCT, _value);
                case (int)eSkillEffectConditionType.MP:
                    return ac.GetValue((int)eAttribute.MP, _value);
                case (int)eSkillEffectConditionType.MP_PCT:
                    return ac.GetValue((int)eAttribute.MP_PCT, _value);
                case (int)eSkillEffectConditionType.X_MP:
                    return ac.GetValue((int)eAttribute.X_MP, _value);
                case (int)eSkillEffectConditionType.X_MP_PCT:
                    return ac.GetValue((int)eAttribute.X_MP_PCT, _value);
                case (int)eSkillEffectConditionType.P_ATK:
                    return ac.GetValue((int)eAttribute.P_ATK, _value);
                case (int)eSkillEffectConditionType.P_ATK_PCT:
                    return ac.GetValue((int)eAttribute.P_ATK_PCT, _value);
                case (int)eSkillEffectConditionType.M_ATK:
                    return ac.GetValue((int)eAttribute.M_ATK, _value);
                case (int)eSkillEffectConditionType.M_ATK_PCT:
                    return ac.GetValue((int)eAttribute.M_ATK_PCT, _value);
                case (int)eSkillEffectConditionType.LV:
                    return ac.GetValue((int)eAttribute.LV, _value);
                case (int)eSkillEffectConditionType.RANK:
                    return ac.GetValue((int)eAttribute.RANK, _value);
                case (int)eSkillEffectConditionType.Num:
                    return _value;
                case (int)eSkillEffectConditionType.StackNum:
                {
                    var effect = _self.SearchBuff(_eID, _receiver);
                    if (effect == null)
                    {
                        return 0;
                    }

                    return effect.Stack_Num;
                }
                case (int)eSkillEffectConditionType.ExecuteNum:
                {
                    var effect = _self.SearchBuff(_eID, _receiver);
                    if (effect == null)
                    {
                        return 0;
                    }

                    return effect.Execute_Num;
                }
                case (int)eSkillEffectConditionType.Random:
                {
                    return _self.Random.Next(0, 100);
                }
            }

            return 0;
        }

        /// <summary>
        /// 执行
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_id"></param>
        /// <param name="_receiver"></param>
        /// <param name="_pos"></param>
        private static void Do(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            _self.HandleA(_id, _receiver, _pos);
        }

        #region Buff

        /// <summary>
        /// 执行Buff效果
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_id"></param>
        /// <param name="_receiver"></param>
        /// <param name="_pos"></param>
        /// <returns></returns>
        private static int ExecuteBuff(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            if (_self.ConditionPass(_id, _receiver, _pos) == 0)
            {
                return 0;
            }

            _self.Do(_id, _receiver, _pos);
            return 1;
        }


        private static void AddBuff(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var setc = _self.GetParentChild<SkillEffectTargetComponent>();
            if (setc == null)
            {
                return;
            }

            using var targets = setc.GetTargets(_id, _receiver, _pos);
            for (int i = 0; i < targets.Count; i++)
            {
                _self.AddBuff(_id, targets[i]);
            }
        }

        private static void AddBuff(this SkillEffectExecutionComponent _self, int _id, Entity _receiver)
        {
            var sc = _receiver.GetChild<SkillComponent>();
            var data = _self.GetEffectData(_id);
            if (sc == null || data == null)
            {
                return;
            }

            var sec = sc.GetChild<SkillEffectComponent>();
            if (sec == null)
            {
                return;
            }

            if (data.IsBuff == 0)
            {
                return;
            }

            //加入等待组
            sec.AddBuffs.Add(new EffectBuff()
            {
                ID = _id,
                A = _self.GetMainEntity(),
                B = _receiver,
            });
        }

        private static void RemoveBuff(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var setc = _self.GetParentChild<SkillEffectTargetComponent>();
            if (setc == null)
            {
                return;
            }

            using var targets = setc.GetTargets(_id, _receiver, _pos);
            for (int i = 0; i < targets.Count; i++)
            {
                _self.RemoveBuff(_id, targets[i]);
            }
        }

        private static void RemoveBuff(this SkillEffectExecutionComponent _self, int _id, Entity _receiver)
        {
            var sc = _receiver.GetChild<SkillComponent>();
            var data = _self.GetEffectData(_id);
            if (sc == null || data == null)
            {
                return;
            }

            var sec = sc.GetChild<SkillEffectComponent>();
            if (sec == null)
            {
                return;
            }

            if (data.IsBuff == 0)
            {
                return;
            }

            //加入等待组
            sec.RemoveBuffs.Add(new EffectBuff()
            {
                ID = _id,
                A = _self.GetMainEntity(),
                B = _receiver,
            });
        }

        private static void DestroyBuff(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var setc = _self.GetParentChild<SkillEffectTargetComponent>();
            if (setc == null)
            {
                return;
            }

            using var targets = setc.GetTargets(_id, _receiver, _pos);
            for (int i = 0; i < targets.Count; i++)
            {
                _self.DestroyBuff(_id, targets[i]);
            }
        }

        private static void DestroyBuff(this SkillEffectExecutionComponent _self, int _id, Entity _receiver)
        {
            var buff = _self.SearchBuff(_id, _receiver);
            if (buff != null)
            {
                buff.IsDestroy = true;
            }
        }

        private static SkillEffectBuff SearchBuff(this SkillEffectExecutionComponent _self, int _id, Entity _receiver)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var sc = _receiver.GetChild<SkillComponent>();
            if (dc == null || sc == null)
            {
                return null;
            }

            var data = dc.LoadDataTable<DRSkillEffect>().GetData(_id);
            if (data == null)
            {
                return null;
            }

            if (data.IsBuff == 0)
            {
                return null;
            }

            return (SkillEffectBuff)sc.GetSkillEffect(_id);
        }

        /// <summary>
        /// 更新加Buff
        /// </summary>
        /// <param name="_self"></param>
        private static void UpdateAddBuffs(this SkillEffectExecutionComponent _self)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var sec = _self.GetParent<SkillEffectComponent>();
            if (sec == null || dc == null)
            {
                return;
            }

            for (int i = 0; i < sec.AddBuffs.Count; i++)
            {
                int id = sec.AddBuffs[i].ID;
                var aEntity = sec.AddBuffs[i].A.Entity;
                var bEntity = sec.AddBuffs[i].B.Entity;
                var data = dc.LoadDataTable<DRSkillEffect>().GetData(id);
                SkillEffectBuff find;
                sec.NowBuffs.TryGetValue(id, out find);
                if (find == null)
                {
                    //新Buff处理
                    find = ObjectGenerater.Instance.Fetch<SkillEffectBuff>();
                    find.ID = id;
                    find.Accrue_Time = 0;
                    if (data.IsCooldown == 0)
                    {
                        find.Cooldown_Time = 0;
                    }
                    else
                    {
                        find.Cooldown_Time = Formula.TM(data.Cooldown);
                    }

                    if (data.Duration == -1)
                    {
                        find.Remaining_Time = data.Duration;
                    }
                    else
                    {
                        find.Remaining_Time = Formula.TM(data.Duration);
                    }

                    find.Stack_Num = 0;
                    find.Before_Stack_Num = 0;
                    find.A = aEntity;
                    find.B = bEntity;
                    find.IsDestroy = false;
                    sec.NowBuffs.Add(find.ID, find);

                    //生成的时候检测层数执行
                    if (data.StackMax != -1)
                    {
                        find.Stack_Num = data.StackNum;
                        if (find.Stack_Num > data.StackMax)
                        {
                            find.Stack_Num = data.StackMax;
                        }

                        _self.UpdateStackBuff(find.ID);
                    }
                }
                else
                {
                    //叠加层数处理
                    if (data.StackMax != -1)
                    {
                        if (find.Stack_Num < data.StackMax)
                        {
                            find.Before_Stack_Num = find.Stack_Num;
                            find.Stack_Num += data.StackPlusNum;
                            if (find.Stack_Num > data.StackMax)
                            {
                                find.Stack_Num = data.StackMax;
                            }

                            _self.UpdateStackBuff(find.ID);
                        }
                    }

                    if (data.Duration != -1)
                    {
                        if (data.IsReDuration == 1)
                        {
                            find.Remaining_Time = Formula.TM(data.Duration);
                        }
                    }
                }
            }

            sec.AddBuffs.Clear();
        }

        /// <summary>
        /// 更新现有Buff
        /// </summary>
        /// <param name="_self"></param>
        private static void UpdateBuffs(this SkillEffectExecutionComponent _self)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var sec = _self.GetParent<SkillEffectComponent>();

            if (dc == null || sec == null)
            {
                return;
            }

            _self.Clears.Clear();

            FP deltaTime = Time.deltaTime;

            var buffs = sec.NowBuffs;
            var table = dc.LoadDataTable<DRSkillEffect>();
            foreach (var buff in buffs.Values)
            {
                var data = table.GetData(buff.ID);
                if (data == null)
                {
                    continue;
                }

                if (buff.IsDestroy)
                {
                    _self.Clears.Add(buff.ID);
                    continue;
                }

                //累计时间
                buff.Accrue_Time += deltaTime;

                //剩余时间
                if ((int)buff.Remaining_Time != -1)
                {
                    if (buff.Remaining_Time > 0)
                    {
                        buff.Remaining_Time -= deltaTime;
                        if (buff.Remaining_Time <= 0)
                        {
                            buff.Remaining_Time = 0;
                            _self.Clears.Add(buff.ID);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }

                //冷却时间
                if ((int)buff.Cooldown_Time != -1)
                {
                    if (buff.Cooldown_Time > 0)
                    {
                        buff.Cooldown_Time -= deltaTime;
                        if (buff.Cooldown_Time > 0)
                        {
                            continue;
                        }

                        buff.Cooldown_Time = 0;
                    }
                }

                //对象是否都存在
                if (buff.A.Entity == null || buff.B.Entity == null)
                {
                    continue;
                }

                //帧更新中不处理叠变化
                if (data.EffectAType == (int)eSkillEffectAType.StackChange)
                {
                    continue;
                }

                //A->B执行效果
                var seec = (SkillEffectExecutionComponent)_self.GetEntitySkillEffectExecutionComponent(buff.A.Entity);
                if (seec == null)
                {
                    continue;
                }

                if (seec.ExecuteBuff(buff.ID, buff.B.Entity, _self.GetEntityPos(buff.B.Entity)) == 0)
                {
                    continue;
                }

                //执行次数增加
                buff.Execute_Num += -1;

                if ((int)buff.Cooldown_Time != -1)
                {
                    //进入冷却
                    buff.Cooldown_Time = Formula.TM(data.Cooldown);
                }
            }

            //移除
            for (int i = 0; i < _self.Clears.Count; i++)
            {
                _self.RemoveBuff(_self.Clears[i], _self.GetMainEntity());
            }
        }

        /// <summary>
        /// 更新移除Buff
        /// </summary>
        /// <param name="_self"></param>
        private static void UpdateRemoveBuffs(this SkillEffectExecutionComponent _self)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            var sec = _self.GetParent<SkillEffectComponent>();
            if (dc == null || sec == null)
            {
                return;
            }

            for (int i = 0; i < sec.RemoveBuffs.Count; i++)
            {
                int id = sec.RemoveBuffs[i].ID;
                var aEntity = sec.RemoveBuffs[i].A.Entity;
                var bEntity = sec.RemoveBuffs[i].B.Entity;
                var data = dc.LoadDataTable<DRSkillEffect>().GetData(id);
                SkillEffectBuff find;
                sec.NowBuffs.TryGetValue(id, out find);
                if (find != null)
                {
                    bool isClear = true;
                    if (data.StackMax != -1)
                    {
                        find.Before_Stack_Num = find.Stack_Num;
                        //被销毁
                        if (find.IsDestroy || data.IsEndDuration == 1)
                        {
                            find.Stack_Num = 0;
                            _self.UpdateStackBuff(find.ID);
                        }
                        else
                        {
                            find.Stack_Num -= data.StackMinusNum;
                            if (find.Stack_Num <= 0)
                            {
                                find.Stack_Num = 0;
                            }

                            _self.UpdateStackBuff(find.ID);
                            if (find.Stack_Num > 0)
                            {
                                //未移除则刷新剩余时间
                                find.Remaining_Time = Formula.TM(data.Duration);
                                isClear = false;
                            }
                        }
                    }

                    if (isClear)
                    {
                        sec.NowBuffs.Remove(find.ID);
                        ObjectGenerater.Instance.Recycle(find);
                    }
                }
            }

            sec.RemoveBuffs.Clear();
        }

        /// <summary>
        /// 更新Buff层数
        /// </summary>
        /// <param name="_self"></param>
        /// <param name="_id"></param>
        private static void UpdateStackBuff(this SkillEffectExecutionComponent _self, int _id)
        {
            var data = _self.GetEffectData(_id);
            var sec = _self.GetParent<SkillEffectComponent>();
            if (data == null || sec == null)
            {
                return;
            }

            //A->B执行效果
            SkillEffectBuff buff;
            sec.NowBuffs.TryGetValue(_id, out buff);
            if (buff != null)
            {
                if (data.EffectAType == (int)eSkillEffectAType.StackChange)
                {
                    if (buff.A.Entity == null || buff.B.Entity == null)
                    {
                        return;
                    }

                    var seec = (SkillEffectExecutionComponent)_self.GetEntitySkillEffectExecutionComponent(buff.A.Entity);
                    seec?.ExecuteBuff(_id, buff.B.Entity, _self.GetEntityPos(buff.B.Entity));
                }
            }
        }

        #endregion

        #region 通用

        private static DRSkillEffect GetEffectData(this SkillEffectExecutionComponent _self, int _id)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            if (dc == null)
            {
                return null;
            }

            return dc.LoadDataTable<DRSkillEffect>().GetData(_id);
        }

        private static Entity GetEntitySkillEffectExecutionComponent(this SkillEffectExecutionComponent _self, Entity _entity)
        {
            var sc = _entity?.GetChild<SkillComponent>();
            var sce = sc?.GetChild<SkillEffectComponent>();
            var seec = sce?.GetChild<SkillEffectExecutionComponent>();
            return seec;
        }

        private static TSVector GetEntityPos(this SkillEffectExecutionComponent _self, Entity _entity)
        {
            if (_entity == null)
            {
                return new TSVector();
            }

            var tc = _entity.GetChild<TransformComponent>();
            if (tc == null)
            {
                return new TSVector();
            }

            return tc.P;
        }

        private static TSVector GetMainEntityPos(this SkillEffectExecutionComponent _self)
        {
            return _self.GetEntityPos(_self.GetMainEntity());
        }

        private static Entity GetMainEntity(this SkillEffectExecutionComponent _self)
        {
            return _self.Parent.Parent.Parent;
        }

        [Conditional("DEBUG_SHOW")]
        private static void RegisterLog(this SkillEffectExecutionComponent _self, string _message)
        {
            var sc = _self.GetSceneChild<Statistic>();
            if (sc != null)
            {
                sc.Statistic("<color=#FFA500>" + _message + "</color>");
            }
        }

        #endregion

        #region 效果

        private static void HandleA(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            switch (data.EffectAType)
            {
                case (int)eSkillEffectAType.Normal:
                    _self.Normal(_id, _receiver, _pos);
                    break;
                case (int)eSkillEffectAType.StackChange:
                    _self.StackChange(_id, _receiver, _pos);
                    break;
                case (int)eSkillEffectAType.StackNum:
                    _self.StackNum(_id, _receiver, _pos);
                    break;
                case (int)eSkillEffectAType.Count:
                    _self.Count(_id, _receiver, _pos);
                    break;
                case (int)eSkillEffectAType.CountAttribute:
                    _self.CountAttribute(_id, _receiver, _pos);
                    break;
            }
        }

        private static void Normal(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            _self.HandleB(_id, _receiver, _pos, 1);
        }

        private static void StackChange(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            //只有Buff才处理
            if (data.IsBuff == 0)
            {
                return;
            }

            var buff = _self.SearchBuff(_id, _receiver);
            int dif = buff.Stack_Num - buff.Before_Stack_Num;
            if (dif == 0)
            {
                return;
            }

            _self.HandleB(_id, _receiver, _pos, dif);
        }

        private static void StackNum(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            //只有Buff才处理
            if (data.IsBuff == 0)
            {
                return;
            }

            //获取Buff
            var buff = _self.SearchBuff(_id, _receiver);
            if (buff == null)
            {
                return;
            }

            _self.HandleB(_id, _receiver, _pos, buff.Stack_Num);
        }

        private static void Count(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            if (data.Count <= 0)
            {
                return;
            }

            for (int i = 0; i < data.Count; i++)
            {
                _self.HandleB(_id, _receiver, _pos, 1);
            }
        }

        private static void CountAttribute(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            FP value = 0;
            var acA = _self.GetMainEntity().GetChild<AttributeComponent>();
            for (int i = 0; i < data.AttributeTypes.Length; i++)
            {
                value += acA.GetValue(data.AttributeTypes[i], data.AttributeValues[i]);
            }

            for (int i = 0; i < value; i++)
            {
                _self.HandleB(_id, _receiver, _pos, 1);
            }
        }


        private static void HandleB(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos, FP _multiply)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            switch (data.EffectBType)
            {
                case (int)eSkillEffectBType.P_ATK_Damge:
                case (int)eSkillEffectBType.M_ATK_Damge:
                    _self.Damage(_id, _receiver, _pos, _multiply);
                    break;
                case (int)eSkillEffectBType.Normal_Rewards:
                    _self.Reward(_id, _receiver, _pos, _multiply);
                    break;
                case (int)eSkillEffectBType.Excute_Effect:
                case (int)eSkillEffectBType.Remove_Effect:
                case (int)eSkillEffectBType.Destroy_Effect:
                    _self.Effect(_id, _receiver, _pos, _multiply);
                    break;
                case (int)eSkillEffectBType.P_ATK_Health_HP:
                case (int)eSkillEffectBType.M_ATK_Health_HP:
                case (int)eSkillEffectBType.P_ATK_Health_MP:
                case (int)eSkillEffectBType.M_ATK_Health_MP:
                    _self.Health(_id, _receiver, _pos, _multiply);
                    break;
                case (int)eSkillEffectBType.Line_Projectile_Item:
                    _self.Projectile(_id, _receiver, _pos, _multiply);
                    break;
            }
        }

        private static void Damage(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos, FP _multiply)
        {
            var setc = _self.GetParentChild<SkillEffectTargetComponent>();
            if (setc == null)
            {
                return;
            }

            using var targets = setc.GetTargets(_id, _receiver, _pos);
            for (int i = 0; i < targets.Count; i++)
            {
                _self.Damage(_id, targets[i], _multiply);
            }
        }

        private static void Damage(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, FP _multiply)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            //施加者
            var acA = _self.GetMainEntity().GetChild<AttributeComponent>();
            //接收者
            var acB = _receiver.GetChild<AttributeComponent>();
            //伤害合并
            FP value = 0;
            for (int i = 0; i < data.AttributeTypes.Length; i++)
            {
                value += acA.GetValue(data.AttributeTypes[i], data.AttributeValues[i]);
            }

            value *= _multiply;

            ePowerType type = ePowerType.Physics;
            switch (data.EffectBType)
            {
                case (int)eSkillEffectBType.P_ATK_Damge:
                    type = ePowerType.Physics;
                    break;
                case (int)eSkillEffectBType.M_ATK_Damge:
                    type = ePowerType.Magic;
                    break;
            }

            _self.RegisterLog(
                $"【伤害|{data.Name}】" +
                $"【{acA.Attribute.Name}】" +
                " 对 " +
                $"【{acB.Attribute.Name}】"
            );
            acB.OnDamage(acA, value, type, false);
        }

        private static void Reward(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos, FP _multiply)
        {
            var setc = _self.GetParentChild<SkillEffectTargetComponent>();
            if (setc == null)
            {
                return;
            }

            using var targets = setc.GetTargets(_id, _receiver, _pos);
            for (int i = 0; i < targets.Count; i++)
            {
                _self.Reward(_id, targets[i], _multiply);
            }
        }

        private static void Reward(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, FP _multiply)
        {
            var data = _self.GetEffectData(_id);
            var reward = _self.GetSceneChild<Reward>();
            if (data == null || reward == null)
            {
                return;
            }

            //施加者
            var acA = _self.GetMainEntity().GetChild<AttributeComponent>();
            //接收者
            var acB = _receiver.GetChild<AttributeComponent>();
            _self.RegisterLog(
                $"【奖励|{data.Name}】" +
                $"【{acA.Attribute.Name}】" +
                " 对 " +
                $"【{acB.Attribute.Name}】"
            );

            switch (data.EffectBType)
            {
                case (int)eSkillEffectBType.Normal_Rewards:
                    //获得奖励
                    for (int i = 0; i < data.RewardIDs.Length; i++)
                    {
                        reward.ChangeReward(_receiver, data.RewardIDs[i], data.RewardValues[i] * _multiply);
                    }

                    break;
            }
        }

        private static void Effect(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos, FP _multiply)
        {
            var setc = _self.GetParentChild<SkillEffectTargetComponent>();
            if (setc == null)
            {
                return;
            }

            using var targets = setc.GetTargets(_id, _receiver, _pos);
            for (int i = 0; i < targets.Count; i++)
            {
                _self.Effect(_id, targets[i], _multiply);
            }
        }

        private static void Effect(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, FP _multiply)
        {
            var sc = _receiver.GetChild<SkillComponent>();
            if (sc == null)
            {
                return;
            }

            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            var eData = _self.GetEffectData(data.EffectID);
            if (eData == null)
            {
                return;
            }

            var pos = _self.GetEntityPos(_receiver);

            for (int i = 0; i < _multiply; i++)
            {
                switch (data.EffectBType)
                {
                    case (int)eSkillEffectBType.Excute_Effect:
                        _self.Execute(eData.ID, _receiver, pos);
                        break;
                    case (int)eSkillEffectBType.Remove_Effect:
                        _self.Remove(eData.ID, _receiver, pos);
                        break;
                    case (int)eSkillEffectBType.Destroy_Effect:
                        _self.Destroy(eData.ID, _receiver, pos);
                        break;
                }
            }
        }

        private static void Health(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos, FP _multiply)
        {
            var setc = _self.GetParentChild<SkillEffectTargetComponent>();
            if (setc == null)
            {
                return;
            }

            using var targets = setc.GetTargets(_id, _receiver, _pos);
            for (int i = 0; i < targets.Count; i++)
            {
                _self.Health(_id, targets[i], _multiply);
            }
        }

        private static void Health(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, FP _multiply)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            //施加者
            var acA = _self.GetMainEntity().GetChild<AttributeComponent>();
            //接收者
            var acB = _receiver.GetChild<AttributeComponent>();
            //治疗合并
            FP value = 0;
            for (int i = 0; i < data.AttributeTypes.Length; i++)
            {
                value += acA.GetValue(data.AttributeTypes[i], data.AttributeValues[i]);
            }

            value *= _multiply;

            int mode = 0;
            ePowerType type = ePowerType.Physics;
            switch (data.EffectBType)
            {
                case (int)eSkillEffectBType.P_ATK_Health_HP:
                    type = ePowerType.Physics;
                    mode = 0;
                    break;
                case (int)eSkillEffectBType.M_ATK_Health_HP:
                    type = ePowerType.Magic;
                    mode = 0;
                    break;
                case (int)eSkillEffectBType.P_ATK_Health_MP:
                    type = ePowerType.Physics;
                    mode = 1;
                    break;
                case (int)eSkillEffectBType.M_ATK_Health_MP:
                    type = ePowerType.Magic;
                    mode = 1;
                    break;
            }

            _self.RegisterLog(
                $"【恢复|{data.Name}】" +
                $"【{acA.Attribute.Name}】" +
                " 对 " +
                $"【{acB.Attribute.Name}】"
            );
            if (mode == 0)
            {
                acB.OnHealth(acA, value, 0, type);
            }
            else
            {
                acB.OnHealth(acA, 0, value, type);
            }
        }

        private static void Projectile(this SkillEffectExecutionComponent _self, int _id, Entity _receiver, TSVector _pos, FP _multiply)
        {
            var data = _self.GetEffectData(_id);
            if (data == null)
            {
                return;
            }

            for (int i = 0; i < _multiply; i++)
            {
                switch (data.EffectBType)
                {
                    case (int)eSkillEffectBType.Line_Projectile_Item:
                        var item = _self.GetScene().AddChild<SkillEffectLineProjectileItem, int, TSVector>(data.ItemID, _self.GetMainEntityPos());
                        item.SetParameters(_self.GetMainEntity(), _self.GetMainEntityPos(), _pos);
                        break;
                }
            }
        }

        #endregion
    }
}